Java开发规范/习惯

您所在的位置:网站首页 mybatis pagehelper 返回dto Java开发规范/习惯

Java开发规范/习惯

2023-04-05 11:52| 来源: 网络整理| 查看: 265

自定义枚举类自定义异常信息统一返回信息全局异常处理统一日志打印测试

异常 日志在后端框架开发中能够抽取出来的公共部分有以下部分

自定义枚举类自定义异常信息统一返回信息全局异常处理统一日志打印 自定义枚举类对于一些经常返回的错误信息,可以将其抽取出来封装成公共部分,然后将变化的作为参数传入。例如在业务中经常要校验某个字段是否为空,如果为空的话就要返回错误信息xxx字段不能为空,那么为什么不将xxx作为一个变量参数传递过来呢。于是就想到了用枚举类定义异常信息,然后用String.format()方法进行转义public enum ResponseInfoEnum { SUCCESS(ResponseResult.OK,"处理成功"), PARAM_LENGTH_ERROR(ResponseResult.ERROR, "参数:%s,长度错误,max length: %s"), REQ_PARAM_ERROR(ResponseResult.ERROR, "请求报文必填参数%s缺失"),; private Integer code; private String message; ResponseInfoEnum(Integer code, String message) { this.code = code; this.message = message; } public Integer getCode() { return code; } public String getMessage() { return message; }} 使用方法如下String.format(ResponseInfoEnum.REQ_PARAM_ERROR.getMessage(),"testValue") 可以看到生成的错误信息是请求报文必填参数testValue缺失 自定义异常信息首先需要知道为什么要用自定义异常信息呢?使用它有什么好处呢? 首先开发中肯定是分模块进行开发的,所以首先统一了自定义异常类就统一了对外异常的展示方式。使用自定义异常继承相关的异常来抛出处理后的异常信息可以隐藏底层的异常,这样更安全,异常信息也更加的直观。自定义异常可以抛出自己想要抛出的信息,可以通过抛出的信息区分异常发生的位置,根据异常名就可以知道哪里有异常,根据异常提示信息进行程序修改。有时候遇到某些校验或者问题时,需要直接结束掉当前的请求,这时便可以通过抛出自定义异常来结束,如果项目中使用了SpringMVC比较新的版本的话有控制器增强,可以通过@ControllerAdvice注解写一个控制器增强类来拦截自定义的异常并响应给前端相应的信息。

自定义异常需要继承RuntimeException

public class CheckException extends RuntimeException{ public CheckException() { } public CheckException(String message) { super(message); } public CheckException(ResponseInfoEnum responseInfoEnum,String ...strings) { super(String.format(responseInfoEnum.getMessage(),strings)); }}

统一返回信息

接触的最多的项目就是前后端交互的项目了。所以有一个统一的返回信息不仅对前端来说更加便利,对于后面的AOP代理也有很大的好处。

@Data@NoArgsConstructorpublic class ResponseResult { public static final Integer OK = 0; public static final Integer ERROR = 100; private Integer code; private String message; private T data;}

这样前后端进行交互时就会更加便利了,如果要取业务数据那么就从data中取,去过要取是否成功的标志,那么就从code码中取,如果要取后端返回的信息,那么就从message中取。

全局异常处理

在之前的项目中每个Controller方法中都充斥着try....catch...的代码,而catch后的代码都是大同小异,都是封装了一下返回的错误信息之类的。那么为什么不将这些代码抽取出来,利用Spring的全局异常处理简化代码。

@Slf4j@ControllerAdvicepublic class ControllerExceptionHandler { @ExceptionHandler(value = Exception.class) @ResponseBody public ResponseResult defaultErrorHandler(HttpServletRequest request, Exception exception){ log.error(ControllerLog.getLogPrefix()+"Exception: {}"+exception); return handleErrorInfo(exception.getMessage()); } @ExceptionHandler(CheckException.class) @ResponseBody public ResponseResult checkExceptionHandler(HttpServletRequest request, CheckException exception){ return handleErrorInfo(exception.getMessage()); } private ResponseResult handleErrorInfo(String message) { ResponseResult responseEntity = new ResponseResult(); responseEntity.setMessage(message); responseEntity.setCode(ResponseResult.ERROR); responseEntity.setData(message); ControllerLog.destoryThreadLocal(); return responseEntity; }}

其中全局异常处理中,自定义的异常就没有打印日志,因为对于自定义的异常是已知的异常,并且错误信息也已经很明确的返回了。而对于未知异常例如Exception就属于未知的异常,就需要打印日志,如果这里有特殊需求,例如发短信、发邮件通知相关人员的话,这里也能够进行全局的配置。

统一日志打印

统一日志打印只是将项目中公共的打印日志抽取出来,利用AOP来进行打印,例如项目中基本上每个Controller方法的入参和出参都会打印,所以就将此部分抽取出来进行统一管理。

@Slf4j@Aspect@Componentpublic class ControllerLog { private static final ThreadLocal START_TIME_THREAD_LOCAL = new NamedThreadLocal("ThreadLocal StartTime"); private static final ThreadLocal LOG_PREFIX_THREAD_LOCAL = new NamedThreadLocal("ThreadLocal LogPrefix"); /** * Before : 在方法执行前进行切面 * execution : 定义切面表达式 *

public * com.example.javadevelopmentframework.javadevelopmentframework.controller..*.*(..)) * public :匹配所有目标类的public方法,不写则匹配所有访问权限 * 第一个* :方法返回值类型,*代表所有类型 * 第二个* :包路径的通配符 * 第三个..* :表示impl这个目录下所有的类,包括子目录的类 * 第四个*(..) : *表示所有任意方法名,..表示任意参数 *

* @param */ @Pointcut("execution(public * com.example.javadevelopmentframework.javadevelopmentframework.controller..*.*(..))") public void exectionMethod(){} @Before("exectionMethod()") public void doBefore(JoinPoint joinPoint){ START_TIME_THREAD_LOCAL.set(System.currentTimeMillis()); StringBuilder argsDes = new StringBuilder(); //获取类名 String className = joinPoint.getSignature().getDeclaringType().getSimpleName(); //获取方法名 String methodName = joinPoint.getSignature().getName(); //获取传入目标方法的参数 Object[] args = joinPoint.getArgs(); for (int i = 0; i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3